/**
 * @{#}VbaoChargeSystemHandler.java Created on Dec 6, 2015 5:41:54 PM
 * <p>
 * Copyright (c) Dec 6, 2015 by ZHONGBO software.
 */
package com.fingard.dsp.bank.directbank.vbao03.trade;

/**
 * @author 作者 E-mail:lirp@chinavbao.com 
 * @version 1.0
 * 类说明 
 */

import com.vbao.service.trade.utils.Base64;
import com.vbao.service.trade.utils.RSAUtil;
import com.vbao.service.trade.utils.XmlUtils;
import org.dom4j.DocumentException;

import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.util.*;

public class VbaoChargeSystemHandler {
    private static final List<String> not_sign_attrs = new ArrayList<String>();

    static {
        not_sign_attrs.add("Sign");
        not_sign_attrs.add("SignType");
        not_sign_attrs.add("BatchBankCode");
        not_sign_attrs.add("ResultCode");
        not_sign_attrs.add("ErrCode");
        not_sign_attrs.add("Description");
    }

    private List<String> getSortKey(SortedMap<String, ?> receiveData) {
        List<String> attrs = new ArrayList<String>();
        for (String key : receiveData.keySet()) {
            attrs.add(key);
        }
        Arrays.sort(attrs.toArray(new Object[0]));
        return attrs;
    }

    private byte[] getMD(byte[] inByte) {
        if (inByte == null) {
            return null;
        }
        byte[] hash = null;
        try {
            MessageDigest tMessageDigest = MessageDigest.getInstance("MD5");
            tMessageDigest.update(inByte);
            hash = tMessageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return hash;
    }

    /*
     * 3.计算sign值
     */
    private String getSignContent(SortedMap<String, ?> receiveData) {
        try {
            List<String> keys = getSortKey(receiveData);

            StringBuffer signContent = new StringBuffer("");

            for (String key : keys) {
                Object obj = receiveData.get(key);
                if (!(obj instanceof String)) {
                    continue;
                }
                String content = (String) obj;

                if ((content == null) || (content.length() <= 0) || (not_sign_attrs.contains(key)) || content.equals("null") || ("").equals(content))
                    continue;
                if ((signContent != null) && (signContent.length() > 0)) {
                    signContent.append("&");
                }

                if ((content != null) && (content.trim().length() > 0)) {
                    signContent.append(key).append("=").append(content);
                }
            }
            System.out.println("签名:" + signContent.toString());
            return signContent.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 4.MD5加密
     */
    private String getStrMD(String str, String InputCharset) {
        if (str == null)
            return null;
        byte[] inByte = null;
        try {
            inByte = str.getBytes(InputCharset);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        byte[] outByte = getMD(inByte);
        return byteToStr(outByte);
    }

    private String byteToStr(byte[] b) {
        if (b == null) {
            return null;
        }
        String hs = "";
        for (int n = 0; n < b.length; n++) {
            int v = b[n] & 0xFF;
            if (v < 16)
                hs = hs + "0";
            hs = hs + Integer.toString(v, 16).toUpperCase();
        }
        return hs;
    }

    public String http(String url, String string1, String InputCharset) {
        if (null == url || "".equals(url.trim())) {
            System.out.println("发送地址为空");
            return null;
        }
        URL u = null;
        HttpURLConnection con = null;
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setConnectTimeout(120000);
            con.setReadTimeout(120000);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), InputCharset);
            osw.write(string1);
            osw.flush();
            osw.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.disconnect();
            }

        }

        StringBuffer buffer = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), InputCharset));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return buffer.toString();
    }

    /**
     * https协议
     *
     * @param httpsUrl
     * @param xmlStr
     * @param InputCharset
     * @return
     */
    public String postHttps(String httpsUrl, String xmlStr, String InputCharset) {
        if (httpsUrl == null || httpsUrl == "") {
            return null;
        }

        if (xmlStr == null || xmlStr == "") {
            return null;
        }
        HttpsURLConnection urlCon = null;
        try {
            urlCon = (HttpsURLConnection) (new URL(httpsUrl)).openConnection();

            // HttpsURLConnection.setDefaultHostnameVerifier(hv);
            urlCon.setDoInput(true);
            urlCon.setDoOutput(true);
            urlCon.setRequestMethod("POST");
            // urlCon.setHostnameVerifier(new HostnameVerifier() {
            // @Override
            // public boolean verify(String hostname, SSLSession session) {
            // return true;
            // }
            // });
            urlCon.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            urlCon.setRequestProperty("Content-Length", String.valueOf(xmlStr.getBytes().length));
            urlCon.setUseCaches(false);
            // 设置为gbk可以解决服务器接收时读取的数据中文乱码问题
            urlCon.getOutputStream().write(xmlStr.getBytes(InputCharset));

            urlCon.getOutputStream().flush();
            urlCon.getOutputStream().close();
            BufferedReader in = new BufferedReader(new InputStreamReader(urlCon.getInputStream(), InputCharset));
            StringBuffer strBuff = new StringBuffer();
            String line;
            while ((line = in.readLine()) != null) {
                strBuff.append(line);
            }
            return strBuff.toString();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String converter(SortedMap<String, String> dataMap, String InputCharset, boolean flag) throws UnsupportedEncodingException {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        strBuilder.append("<TRequest>");
        Set<String> objSet = dataMap.keySet();
        for (String key : objSet) {
            if (key == null || "null".equals(key) || "".equals(key)) {
                continue;
            }
            strBuilder.append("<").append(key.trim()).append(">");
            strBuilder.append(dataMap.get(key) == null ? "" : dataMap.get(key).trim());
            strBuilder.append("</").append(key.trim()).append(">");
        }
        strBuilder.append("</TRequest>");

        String xml = "";
        if (flag) {
            xml = "reqmsg=" + Base64.encode(strBuilder.toString(), InputCharset);
        } else {
            xml = strBuilder.toString();
        }

        return xml;
    }

    /**
     * 讲XML进行RSA加密
     *
     * @throws Exception
     */
    private String converterRSA(SortedMap<String, String> dataMap, String InputCharset, String publicKeyPath) throws Exception {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        strBuilder.append("<TRequest>");
        Set<String> objSet = dataMap.keySet();
        for (String key : objSet) {
            if (key == null || "null".equals(key) || "".equals(key)) {
                continue;
            }
            strBuilder.append("<").append(key.trim()).append(">");
            strBuilder.append(dataMap.get(key) == null ? "" : dataMap.get(key).trim());
            strBuilder.append("</").append(key.trim()).append(">");
        }
        strBuilder.append("</TRequest>");
        System.out.println("加密前：" + strBuilder.toString());

        // 使用服务端公钥进行RSA加密
        PublicKey publicKey = RSAUtil.getRSAPublicKeyByFileSuffix(publicKeyPath, "pem", "RSA");
        byte[] plainBytes = strBuilder.toString().getBytes("utf-8");
        String encrtptStr = new String(Base64.encode(RSAUtil.encrypt(plainBytes, publicKey, 2048, 11, "RSA/ECB/PKCS1Padding")), "UTF-8");
        System.out.println("encode前的值:" + encrtptStr);
        String xml = "reqmsg=" + URLEncoder.encode(URLEncoder.encode(encrtptStr));// http设置的application/x-www-form-urlencoded则需要encode2次
        // String xml = "reqmsg="+ URLEncoder.encode(encrtptStr);
        return xml;
    }

    public boolean isBase64Flag(String reqmsg, String InputCharset) {
        try {
            return Base64.isArrayByteBase64(reqmsg.getBytes(InputCharset));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return false;
    }

    public String creatOriXml(String encXml, String InputCharset) {
        String returnXml = "";
        if (encXml != null && !encXml.equals("")) {
            try {
                returnXml = Base64.decode(encXml, InputCharset);

            } catch (UnsupportedEncodingException e) {

            }
        }
        return returnXml;
    }

    public boolean verifySignature(String returnOriDKPayxml, String password, String InputCharset) {
        SortedMap<String, String> value = new TreeMap<String, String>();
        try {
            value = XmlUtils.parseXML2(returnOriDKPayxml, null, value, true);
            System.out.println("===>value:" + value);
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        /*
         * 2016-09-06 liutl comment this for zhufeng verfiy sign error for
         * (String key : value.keySet()) { value.put(key,
         * BeanToMapUtils.URLEncodeParams(key, value.get(key), InputCharset)); }
         */

        if (null != value && value.get("ResultCode").length() > 0) {
            if (value.get("ResultCode").equals("F")) {
                return true;
            }
        }

        String mySign = getStrMD(getSignContent(value) + password, InputCharset);
        System.out.println("mysign:" + mySign);
        if (null != mySign && mySign.length() > 0 && null != value.get("Sign") && value.get("Sign").length() > 0) {
            if (mySign.equals(value.get("Sign"))) {
                return true;
            }
        }
        return false;
    }

    public String httpjson(String url, String string1, String InputCharset) {
        if (null == url || "".equals(url.trim())) {
            System.out.println("发送地址为空");
            return null;
        }
        URL u = null;
        HttpURLConnection con = null;
        try {
            u = new URL(url);
            con = (HttpURLConnection) u.openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setConnectTimeout(120000);
            con.setReadTimeout(120000);
            con.setUseCaches(false);
            con.setRequestProperty("Content-Type", "application/json");
            OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), InputCharset);
            osw.write(string1);
            osw.flush();
            osw.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (con != null) {
                con.disconnect();
            }

        }

        StringBuffer buffer = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), InputCharset));
            String temp;
            while ((temp = br.readLine()) != null) {
                buffer.append(temp);
                buffer.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return buffer.toString();
    }

}
